﻿using System;
using System.Text;
using System.Text.RegularExpressions;

namespace ComTools
{
    public class SmsMessage
    {
        private String _ScaLength = "00";
        /// <summary>
        /// SCA服务中心数据长度,默认 08
        /// </summary>
        public String ScaLength
        {
            get
            {
                return _ScaLength;
            }
            set
            {
                _ScaLength = value;
            }
        }

        private String _ScaTosca = String.Empty;
        /// <summary>
        /// 91:国际型(默认)
        /// 81:国内型
        /// </summary>
        public String ScaTosca
        {
            get
            {
                return _ScaTosca;
            }
            set
            {
                _ScaTosca = value;
            }
        }

        private String _ScaAddress = String.Empty;
        /// <summary>
        /// SCA服务中心地址
        /// </summary>
        public String ScaAddress
        {
            get
            {
                return _ScaAddress;
            }
            set
            {
                value = value.TrimStart('+');
                if (!value.StartsWith("86"))
                {
                    value = "86" + value;
                }
                if (String.IsNullOrEmpty(value))
                {
                    _ScaAddress = "00";
                    _ScaTosca = String.Empty;
                    _ScaLength = String.Empty;
                }
                else
                {
                    _ScaAddress = EncodePhoneNum(value);
                    _ScaTosca = "91";
                    _ScaLength = ((_ScaTosca + _ScaAddress).Length / 2).ToString("X2");
                }
            }
        }

        /// <summary>
        /// PDU第1字节：0x11表示发送PDU
        /// </summary>
        public String FO
        {
            get
            {
                return "11";
            }
            set
            {
            }
        }
        /// <summary>
        /// 短消息参考号码，表示移动台向短消息服务中心提供的短消息序号，范围0-255
        /// 发送模块会自动更改此值，所以默认为00
        /// </summary>
        public String MR
        {
            get
            {
                return "00";
            }
            set
            {
            }
        }

        private String _PhoneLength = "0B";
        /// <summary>
        /// 收信人号码长度，大陆手机为11位，故值为0B
        /// </summary>
        public String PhoneLength
        {
            get
            {
                return _PhoneLength;
            }
            set
            {
                _PhoneNumber = value;
            }
        }

        private String _PhoneToda = "A1";
        /// <summary>
        /// 收信人号码类型：81.国内手机，91.国际手机, A1.未知
        /// </summary>
        public String PhoneToda
        {
            get
            {
                return _PhoneToda;
            }
            set
            {
                _PhoneToda = value;
            }
        }

        private String _PhoneNumber = String.Empty;
        /// <summary>
        /// 收信人号码
        /// </summary>
        public String PhoneNumber
        {
            get
            {
                return _PhoneNumber;
            }
            set
            {
                value = value.TrimStart('+');
                if (value.StartsWith("86"))
                {
                    value = value.TrimStart('8', '6');
                }
                _PhoneLength = value.Length.ToString("X2");
                _PhoneNumber = EncodePhoneNum(value);
                //_PhoneToda = "A1";
            }
        }

        private String _PID = "00";
        /// <summary>
        /// 短消息传输层为高层协议参考，或是远程设备协同工作的标示，需要服务商的支持，但00是所有服务商都支持的，故用00即可
        /// </summary>
        public String PID
        {
            get
            {
                return _PID;
            }
            set
            {
                _PID = value;
            }
        }

        private String _DataEncodingStandardCode = "08";
        /// <summary>
        /// 数据编码方式 08：UCS2编码,00：7Bit编码
        /// </summary>
        public String DataEncodingStandardCode
        {
            get
            {
                return _DataEncodingStandardCode;
            }
            set
            {
                //暂时限制只能使用08编码
                _DataEncodingStandardCode = "08";
            }
        }

        private String _ValidPeriod = "C4";
        /// <summary>
        /// 消息在短信服务中心的存活时间，默认A8 C4
        /// </summary>
        public String ValidPeriod
        {
            get
            {
                return _ValidPeriod;
            }
            set
            {
                _ValidPeriod = value;
            }
        }

        private String _UserDataLength = "04";
        /// <summary>
        /// 用户短信内容长度
        /// </summary>
        public String UserDataLength
        {
            get
            {
                return _UserDataLength;
            }
            set
            {
                _UserDataLength = value;
            }
        }

        private String _UserData;
        /// <summary>
        /// 经过编码的用户短信内容
        /// </summary>
        public String UserData
        {
            get
            {
                return _UserData;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    _UserData = String.Empty;
                }
                else
                {
                    _UserData = Chinese2Hex(value);
                }
                _UserDataLength = (_UserData.Length / 2).ToString("X2");
            }
        }

        private Encoding UnicodeBigEndian = Encoding.BigEndianUnicode;
        private String Chinese2Hex(String chinese)
        {
            if (!String.IsNullOrEmpty(chinese))
            {
                if (DataEncodingStandardCode.Equals("08"))
                {
                    byte[] xx = Encoding.BigEndianUnicode.GetBytes(chinese);
                    return BitConverter.ToString(xx).Replace("-", "");
                }
                else
                {
                    return String.Empty;
                }
            }
            else
            {
                return String.Empty;
            }
        }

        /// <summary>
        /// UCS2编码
        /// </summary>
        /// <param name="src"> UTF-16BE编码的源串</param>
        /// <returns>编码后的UCS2串 </returns>
        public string EncodeUCS2(string src)
        {
            StringBuilder builer = new StringBuilder();
            builer.Append("000800");
            byte[] tmpSmsText = Encoding.Unicode.GetBytes(src);
            builer.Append(tmpSmsText.Length.ToString("X2")); //正文内容长度
            for (int i = 0; i < tmpSmsText.Length; i += 2) //高低字节对调 
            {
                builer.Append(tmpSmsText[i + 1].ToString("X2"));//("X2")转为16进制
                builer.Append(tmpSmsText[i].ToString("X2"));
            }
            builer = builer.Remove(0, 8);

            return builer.ToString();

        }

        /// <summary>
        /// UCS2解码 
        /// </summary>
        /// <param name="src"> UCS2 源串 </param>
        /// <returns> 解码后的UTF-16BE字符串</returns>
        public string DecodeUCS2(string src)
        {
            string decucs = src.Remove(src.IndexOf("\r"));
            string pstr = "^[0-9a-fA-F]+$";
            if (!Regex.IsMatch(decucs, pstr))
            {
                return "非法字符串无法解析！";
            }

            StringBuilder builer = new StringBuilder();

            for (int i = 0; i < decucs.Length; i += 4)
            {
                int unicode_nu = Int32.Parse(decucs.Substring(i, 4), System.Globalization.NumberStyles.HexNumber);
                builer.Append(string.Format("{0}", (char)unicode_nu));
            }

            return builer.ToString();
        }

        public string EncodePhoneNum(String phone)
        {
            StringBuilder sb = new StringBuilder(20);
            if (phone.Length % 2 != 0)
            {
                phone += "F";
            }
            for (int i = 0; i < phone.Length - 1; i += 2)
            {
                sb.Append(phone[i + 1]).Append(phone[i]);
            }
            return sb.ToString();
        }

        public int AtCmgsLength
        {
            get
            {
                sbTemp.Remove(0, sbTemp.Length);
                sbTemp.Append(FO ?? "11").Append(MR ?? "00")
                    .Append(PhoneLength ?? "0B").Append(PhoneToda ?? "81").Append(PhoneNumber)
                    .Append(PID ?? "00").Append(DataEncodingStandardCode ?? "08").Append(ValidPeriod ?? "A8")
                    .Append(UserDataLength ?? "04").Append(UserData ?? "");
                return sbTemp.Length / 2;
            }
        }

        private StringBuilder sbTemp = new StringBuilder();

        public override string ToString()
        {
            sbTemp.Remove(0, sbTemp.Length);

            //UserDataLength = (UserData.Length / 2).ToString("X2");

            sbTemp.Append(ScaLength).Append(ScaTosca).Append(ScaAddress)
                .Append(FO).Append(MR)
                .Append(PhoneLength).Append(PhoneToda).Append(PhoneNumber)
                .Append(PID).Append(DataEncodingStandardCode).Append(ValidPeriod)
                .Append(UserDataLength).Append(UserData ?? "")
                .Append((char)26);

            return sbTemp.ToString();
        }
    }

    public class SmsMessage2
    {
        /// <summary>
        /// SCA服务中心数据长度,默认 08
        /// </summary>
        public String ScaLength { get; set; }
        /// <summary>
        /// 91:国际型(默认)
        /// 81:国内型
        /// </summary>
        public String ScaTosca { get; set; }
        /// <summary>
        /// SCA服务中心地址
        /// </summary>
        public String ScaAddress { get; set; }
        /// <summary>
        /// PDU第1字节：0x11表示发送PDU
        /// </summary>
        public String FO { get; set; }
        /// <summary>
        /// 短消息参考号码，表示移动台向短消息服务中心提供的短消息序号，范围0-255
        /// 发送模块会自动更改此值，所以默认为00
        /// </summary>
        public String MR { get; set; }
        /// <summary>
        /// 收信人号码长度，大陆手机为11位，故值为0B
        /// </summary>
        public String PhoneLength { get; set; }
        /// <summary>
        /// 收信人号码类型：81.国内手机，91.国际手机
        /// </summary>
        public String PhoneToda { get; set; }
        /// <summary>
        /// 收信人号码
        /// </summary>
        public String PhoneNumber { get; set; }
        /// <summary>
        /// 短消息传输层为高层协议参考，或是远程设备协同工作的标示，需要服务商的支持，但00是所有服务商都支持的，故用00即可
        /// </summary>
        public String PID { get; set; }

        private String _DataEncodingStandardCode = "08";
        /// <summary>
        /// 数据编码方式 08：UCS2编码,00：7Bit编码
        /// </summary>
        public String DataEncodingStandardCode
        {
            get
            {
                return _DataEncodingStandardCode;
            }
            set
            {
                //暂时限制只能使用08编码
                _DataEncodingStandardCode = "08";
            }
        }
        /// <summary>
        /// 消息在短信服务中心的存活时间，默认A8
        /// </summary>
        public String ValidPeriod { get; set; }

        /// <summary>
        /// 用户短信内容长度
        /// </summary>
        public String UserDataLength { get; set; }

        private String _UserData;
        /// <summary>
        /// 经过编码的用户短信内容
        /// </summary>
        public String UserData
        {
            get
            {
                return _UserData;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                {
                    _UserData = String.Empty;
                }
                else
                {
                    _UserData = Chinese2Hex(value);
                }
            }
        }

        private Encoding UnicodeBigEndian = Encoding.BigEndianUnicode;
        private String Chinese2Hex(String chinese)
        {
            if (!String.IsNullOrEmpty(chinese))
            {
                if (DataEncodingStandardCode.Equals("08"))
                {
                    byte[] xx = Encoding.BigEndianUnicode.GetBytes(chinese);
                    return BitConverter.ToString(xx).Replace("-", "");
                }
                else
                {
                    return String.Empty;
                }
            }
            else
            {
                return String.Empty;
            }
        }

        /// <summary>
        /// UCS2编码
        /// </summary>
        /// <param name="src"> UTF-16BE编码的源串</param>
        /// <returns>编码后的UCS2串 </returns>
        public string EncodeUCS2(string src)
        {
            StringBuilder builer = new StringBuilder();
            builer.Append("000800");
            byte[] tmpSmsText = Encoding.Unicode.GetBytes(src);
            builer.Append(tmpSmsText.Length.ToString("X2")); //正文内容长度
            for (int i = 0; i < tmpSmsText.Length; i += 2) //高低字节对调 
            {
                builer.Append(tmpSmsText[i + 1].ToString("X2"));//("X2")转为16进制
                builer.Append(tmpSmsText[i].ToString("X2"));
            }
            builer = builer.Remove(0, 8);

            return builer.ToString();

        }

        /// <summary>
        /// UCS2解码 
        /// </summary>
        /// <param name="src"> UCS2 源串 </param>
        /// <returns> 解码后的UTF-16BE字符串</returns>
        public string DecodeUCS2(string src)
        {
            string decucs = src.Remove(src.IndexOf("\r"));
            string pstr = "^[0-9a-fA-F]+$";
            if (!Regex.IsMatch(decucs, pstr))
            {
                return "非法字符串无法解析！";
            }

            StringBuilder builer = new StringBuilder();

            for (int i = 0; i < decucs.Length; i += 4)
            {
                int unicode_nu = Int32.Parse(decucs.Substring(i, 4), System.Globalization.NumberStyles.HexNumber);
                builer.Append(string.Format("{0}", (char)unicode_nu));
            }

            return builer.ToString();
        }

        public string EncodePhoneNum(String phone)
        {
            StringBuilder sb = new StringBuilder(20);
            if (phone.Length % 2 != 0)
            {
                phone += "F";
            }
            for (int i = 0; i < phone.Length - 1; i += 2)
            {
                sb.Append(phone[i + 1]).Append(phone[i]);
            }
            return sb.ToString();
        }

        public int AtCmgsLength
        {
            get
            {
                sbTemp.Clear();
                sbTemp.Append(FO ?? "11").Append(MR ?? "00")
                    .Append(PhoneLength ?? "0B").Append(PhoneToda ?? "81").Append(EncodePhoneNum(PhoneNumber ?? ""))
                    .Append(PID ?? "00").Append(DataEncodingStandardCode ?? "08").Append(ValidPeriod ?? "A8")
                    .Append(UserDataLength ?? "04").Append(UserData ?? "");
                return sbTemp.Length;
            }
        }

        private StringBuilder sbTemp = new StringBuilder();

        public override string ToString()
        {
            sbTemp.Clear();

            ScaLength = String.Format("{0:D2}", (ScaTosca.Length + EncodePhoneNum(ScaAddress).Length) / 2);
            UserDataLength = String.Format("{0:D2}", UserData.Length / 2);

            sbTemp.Append(ScaLength ?? "08").Append(ScaTosca ?? "91").Append(EncodePhoneNum(ScaAddress ?? ""))
                .Append(FO ?? "11").Append(MR ?? "00")
                .Append(PhoneLength ?? "0B").Append(PhoneToda ?? "81").Append(EncodePhoneNum(PhoneNumber ?? ""))
                .Append(PID ?? "00").Append(DataEncodingStandardCode ?? "08").Append(ValidPeriod ?? "A8")
                .Append(UserDataLength ?? "04").Append(UserData ?? "")
                .Append((char)26);

            return sbTemp.ToString();
        }
    }
}